package com.juntu.event_center

import android.text.TextUtils
import android.util.Log
import java.util.*

object EventCenter {

    private val TAG = EventCenter::class.java.simpleName

    /**
     * 监听器列表，支持一对多存储
     */
    private val LISTENER_MAP = HashMap<String, Any>()

    /**
     * 监听器列表锁
     */
    private val LISTENER_LOCK = Any()

    /**
     * 事件对象池
     */
    private val POOL = EventObjectPool(5)

    /**
     * 注册/注销监听器
     *
     * @param toBind   true注册  false注销
     * @param listener 监听器
     * @param topic    单个主题
     */
    fun onBindEvent(toBind: Boolean, listener: EventListener, topic: String) {
        onBindEvent(toBind, listener, arrayOf(topic))
    }

    /**
     * 注册/注销监听器
     *
     * @param toBind   true注册  false注销
     * @param listener 监听器
     * @param topics   多个主题
     */
    fun onBindEvent(toBind: Boolean, listener: EventListener, topics: Array<String>) {
        if (toBind) {
            registerEventListener(listener, topics)
        } else {
            unregisterEventListener(listener, topics)
        }
    }

    /**
     * 注册监听器
     *
     * @param listener 监听器
     * @param topic    单个主题
     */
    fun registerEventListener(listener: EventListener, topic: String) {
        registerEventListener(listener, arrayOf(topic))
    }

    /**
     * 注册监听器
     *
     * @param listener 监听器
     * @param topics   多个主题
     */
    fun registerEventListener(listener: EventListener?, topics: Array<String>?) {
        if (null == listener || null == topics) {
            return
        }

        synchronized(LISTENER_LOCK) {
            for (topic in topics) {
                if (TextUtils.isEmpty(topic)) {
                    continue
                }

                val obj = LISTENER_MAP[topic]
                if (null == obj) {
                    // 还没有监听器，直接放到Map集合
                    LISTENER_MAP[topic] = listener
                } else if (obj is EventListener) {
                    // 有一个监听器
                    val oldListener = obj
                    if (listener === oldListener) {
                        // 去重
                        continue
                    }
                    val list = LinkedList<EventListener>()
                    list.add(oldListener)
                    list.add(listener)
                    LISTENER_MAP[topic] = list
                } else if (obj is List<*>) {
                    // 有多个监听器
                    val listeners = obj as LinkedList<EventListener>?
                    if (listeners!!.indexOf(listener) >= 0) {
                        // 去重
                        continue
                    }
                    listeners.add(listener)
                }
            }
        }
    }

    /**
     * 注销监听器
     *
     * @param listener 监听器
     * @param topic    单个主题
     */
    fun unregisterEventListener(listener: EventListener, topic: String) {
        unregisterEventListener(listener, arrayOf(topic))
    }

    /**
     * 注销监听器
     *
     * @param listener 监听器
     * @param topics   多个主题
     */
    fun unregisterEventListener(listener: EventListener?, topics: Array<String>?) {
        if (null == listener || null == topics) {
            return
        }
        synchronized(LISTENER_LOCK) {
            for (topic in topics) {
                if (TextUtils.isEmpty(topic)) {
                    continue
                }
                val obj = LISTENER_MAP[topic]
                if (null == obj) {
                    continue
                } else if (obj is EventListener) {
                    // 有一个监听器
                    if (obj === listener) {
                        LISTENER_MAP.remove(topic)
                    }
                } else if (obj is List<*>) {
                    // 有多个监听器
                    val listeners = obj as LinkedList<EventListener>?
                    listeners!!.remove(listener)
                }
            }
        }
    }

    /**
     * 同步分发事件
     *
     * @param topic      主题
     * @param msgCode    消息类型
     * @param resultCode 预留参数
     * @param obj        回调返回数据
     */
    fun dispatchEvent(topic: String, msgCode: Int, resultCode: Int, obj: Any) {
        if (!TextUtils.isEmpty(topic)) {
            val event: Event = POOL.get()
            event.topic = topic
            event.msgCode = msgCode
            event.resultCode = resultCode
            event.data = obj
            dispatchEvent(event)
        }
    }

    /**
     * 同步分发事件
     *
     * @param event
     */
    fun dispatchEvent(event: Event?) {
        // 没有监听器，直接跳出代码，无需执行以下代码
        if (LISTENER_MAP.size == 0) {
            return
        }

        if (null != event && !TextUtils.isEmpty(event!!.topic)) {
            val topic = event!!.topic
            // 通知事件监听器处理事件
            var listener: EventListener? = null
            var listeners: LinkedList<EventListener>? = null

            synchronized(LISTENER_LOCK) {
                Log.d(TAG, "dispatchEvent | topic = " + topic + "\tmsgCode = " + event!!.msgCode
                        + "\tresultCode = " + event!!.resultCode + "\tobj = " + event!!.data)
                val obj = LISTENER_MAP[topic] ?: return
                if (obj is EventListener) {
                    listener = obj as EventListener
                } else if (obj is LinkedList<*>) {
                    listeners = obj.clone() as LinkedList<EventListener>
                }
            }

            // 分发事件
            if (null != listener) {
                listener!!.onEvent(topic, event!!.msgCode, event!!.resultCode, event!!.data)
            } else if (null != listeners && listeners!!.size > 0) {
                for (l in listeners!!) {
                    l.onEvent(topic, event!!.msgCode, event!!.resultCode, event!!.data)
                }
            }
            // 把对象放回池里面
            POOL.returnObj(event)
        }
    }
}
